package com.enlorenz.support.bank.iso8583custom.packer;

import com.enlorenz.common.util.CodeUtils;
import com.enlorenz.common.util.ReflectionUtils;
import com.enlorenz.common.util.StringUtils;
import com.enlorenz.support.bank.iso8583custom.Iso8583Constants;
import com.enlorenz.support.bank.iso8583custom.Iso8583Utils;
import com.enlorenz.support.bank.iso8583custom.msg.AbstractIso8583Fields;
import com.enlorenz.support.bank.iso8583custom.msg.IFieldMac;
import com.enlorenz.support.bank.iso8583custom.msg.Iso8583FieldsStandard;
import com.enlorenz.support.bank.iso8583custom.solab.iso8583.IsoMessage;

/**
 * 抽象的iso消息打包解析器
 * @author Karma
 */
public abstract class AbstractIsoMsgGenerator implements IIsoMsgGenerator{
	protected String reqXml; 
	protected String resXml; 
	private int headLength=Iso8583Constants.DEFAULT_HEAD_LENGTH;
	public static final int BIN_HEAD=0;
	public static final int STR_HEAD=1;
	private int headType=STR_HEAD;
	private Class<? extends AbstractIso8583Fields> isoClass
	=Iso8583FieldsStandard.class;
	
	public Class<? extends AbstractIso8583Fields> getIsoClass(){
		return isoClass;
	}
	
	/**
	 * 获取请求类型
	 * @return
	 */
	protected abstract int getReqType();
	
	/**
	 * 获取返回类型
	 * @return
	 */
	protected abstract int getResType();
	
	/**
	 * 填充参数
	 * @param crm
	 */
	protected abstract void fillParams(AbstractIso8583Fields crm,Object attParams);
	
	/**
	 * 初始化，必须执行
	 */
	public AbstractIsoMsgGenerator(){
		reqXml=Iso8583Utils.createParseXml(getReqType(), getIsoClass()); 
		resXml=Iso8583Utils.createParseXml(getResType(), getIsoClass()); 
	}
	
	protected abstract byte [] generateMac(AbstractIso8583Fields crm);
	
	
	
	private IsoMessage parseMsg(String xml,byte[] buff) {
		AbstractIso8583Fields iso=ReflectionUtils.newInstanceClass(getIsoClass());
		IsoMessage im=Iso8583Utils.parse(xml,buff,headLength,iso.getIsoConfig());
		return im;
	} 
	
	
	/**
	 * 打包报文
	 * @param attParams 附加属性
	 * @return 报文字节数组
	 */
	public byte [] pack(Object attParams){
		AbstractIso8583Fields crm=ReflectionUtils.newInstanceClass(getIsoClass());
		fillParams(crm,attParams);
		
		byte [] mac=generateMac(crm);
		if(null!=mac){
			if(crm instanceof IFieldMac){
				IFieldMac fieldMac=(IFieldMac)crm;
				fieldMac.setMac(mac);
			}
		}
		
		if(headType == BIN_HEAD){
			byte[] buff = createMsg(getReqType(),crm,headLength);
			return buff;
		}else if(headType == STR_HEAD){
			byte [] buff=createMsg(getReqType(), crm, 0);
			String headStr=
					StringUtils.appendLeftZero(buff.length,headLength);
			byte[] headBuff=headStr.getBytes();
			return CodeUtils.gatherBytes(headBuff, buff);
		}
		return null;
	}

	protected byte[] createMsg(int type,AbstractIso8583Fields crm,int length) {
		byte [] buff=Iso8583Utils.create(type,crm,length);
		return buff;
	}

	
	public int getHeadLength() {
		return headLength;
	}

	public void setHeadLength(int headLength) {
		this.headLength = headLength;
	}

	public int getHeadType() {
		return headType;
	}

	public void setHeadType(int headType) {
		this.headType = headType;
	}
	
	/**
	 * 解析请求数据
	 * @param buff 数据
	 * @return
	 */
	public IsoMessage parseReq(byte [] buff){
		return parseMsg(reqXml,buff);
	}

	/**
	 * 解析返回数据
	 * @param buff 数据
	 * @return
	 */
	public IsoMessage parseRes(byte [] buff){
		return parseMsg(resXml, buff);
	} 

	/**
	 * 解析请求数据
	 * @param buff 数据
	 * @return
	 */
	public AbstractIso8583Fields parseReq2Object(byte [] buff){
		AbstractIso8583Fields iso=ReflectionUtils.newInstanceClass(getIsoClass());
		iso.load(parseReq(buff));
		return iso;
	} 
	
	/**
	 * 解析返回数据
	 * @param buff 数据
	 * @return
	 */
	public AbstractIso8583Fields parseRes2Object(byte [] buff){
		AbstractIso8583Fields iso=ReflectionUtils.newInstanceClass(getIsoClass());
		iso.load(parseRes(buff));
		return iso;
	} 
}
